package com.hmdp.utils;

import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;

/**
 * @author 大忽悠
 * @create 2022/4/28 19:24
 */
@Component
public class RedisWorker {
  private static final long BEGIN_TIMESTAMP;
  private final StringRedisTemplate stringRedisTemplate;
  private final String INCR_PREFIX="incr:";
  private final String INCR_DELIMITER=":";
    /**
     * 位运算向高位移动的位数,为了给redis自增长key腾出32位的空间
     */
  private final int COUNT_BITS=32;

    public RedisWorker(StringRedisTemplate stringRedisTemplate) {
        this.stringRedisTemplate = stringRedisTemplate;
    }

    static {
      //生产时间戳
      LocalDateTime begin_time = LocalDateTime.of(2002, 1, 2, 0, 0, 0);
     //计算开始时间戳
     BEGIN_TIMESTAMP=begin_time.toEpochSecond(ZoneOffset.UTC);
  }

    /**
     * <P>
     *     基于传入key生成一个全局唯一ID
     * </P>
     * @param keyPrefix 需要为某个传入的key生成一个全局唯一ID
     * @return
     */
  public long nextId(String keyPrefix){
     //1.生成时间戳
      LocalDateTime now = LocalDateTime.now();
      long nowTimeStamp = now.toEpochSecond(ZoneOffset.UTC);
      long timeStampGap=nowTimeStamp-BEGIN_TIMESTAMP;

      //2.生成序列号
      //2.1 获取当前日期,精确到天
      String date = now.format(DateTimeFormatter.ofPattern("yyyy:MM:dd"));
      //redis单个key的自增长有上限,最大为2的64次方
      //如果自增长key不存在,redis会自动创建一个
      Long increment = stringRedisTemplate.opsForValue().increment(INCR_PREFIX + keyPrefix + INCR_DELIMITER + date);
      return timeStampGap << COUNT_BITS | increment;
  }

}
